package org.fluidripple.file;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicInteger;

public class MappedFile {

    private String fileName;
    private int fileSize;
    private File file;
    private FileChannel fileChannel;
    private MappedByteBuffer mappedByteBuffer;
    private final AtomicInteger wrotePosition = new AtomicInteger(0);

    public MappedFile(String fileName, int fileSize) {
        init(fileName,fileSize);
    }

    private void init(String fileName, int fileSize){
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.file = new File(fileName);
        ensureDirOK(this.file.getParent());
        boolean ok = false;
        try {
            this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
            //this.mappedByteBuffer = this.fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, fileSize);
            ok = true;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }finally {
            if (!ok && this.fileChannel != null) {
                //抛出异常，则关闭channel通道
                try {
                    this.fileChannel.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static void ensureDirOK(final String dirName) {
        if (dirName != null) {
            File f = new File(dirName);
            if (!f.exists()) {
                boolean result = f.mkdirs();
            }
        }
    }

    public boolean isFull(int writerSize){
        int size = this.wrotePosition.get()+writerSize;
        return size > fileSize;
    }

    public void appendMessage(String hexDump) {
        byte[] bytes = hexDump.getBytes(StandardCharsets.UTF_8);
        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        while(buffer.hasRemaining()) {
            //向Channel中写入数据
            try {
                fileChannel.write(buffer);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        try {
            fileChannel.force(true);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        this.wrotePosition.addAndGet(bytes.length);


//        int currentPos = this.wrotePosition.get();
//        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
//        byteBuffer.position(currentPos);
//
//        byte[] bytes = hexDump.getBytes(StandardCharsets.UTF_8);
//        ByteBuffer wrap = ByteBuffer.wrap(bytes);
//        byteBuffer.put(wrap.array(),0,bytes.length);
//        this.wrotePosition.addAndGet(bytes.length);
    }
}
